#ifndef COLOR_H
#define COLOR_H
#include <algorithm>
#include <sstream>
#include <vector>
#include <limits>
#include "globals.h"
#include "common/math/col3.h"
#include "spectrum_dynamic.h"
#include "spectrum_static.h"
#include "spectrum_fixed.h"
#include "configurable.h"
namespace gemren
{ 
	
	
	
	
	typedef spectrum_fixed<4> spectrum; //4x4 values
	//typedef spectrum_dynamic spectrum;
	spectrum operator * (const spectrum& s, const spectrum& t) ;
	spectrum operator * (const float f, const spectrum& s) ;
	spectrum operator + (const spectrum& s, const spectrum& t) ;
	
	typedef spectrum color_s;
	typedef spectrum refraction_s;


	//converts single wavelenght or whole spectrum to RGB color
	class color_converter : public configurable
	{
	public:
		typedef embree::Col3f col3f;
		color_converter(const color_s& r, const color_s& g,const color_s& b)
			:r(r), g(g), b(b) 
		{}
		color_converter() 
		{
			float ra[] = { 1.0f, 0.9f, 0.8f,   0.3f, 0.0f, 0.0f,   0.0f, 0.0f, 0.0f };
			float ga[] = { 0.0f, 0.1f, 0.2f,   0.7f, 1.0f, 0.7f,   0.2f, 0.1f, 0.0f };
			float ba[] = { 0.0f, 0.0f, 0.0f,   0.0f, 0.0f, 0.3f,   0.8f, 0.9f, 1.0f };
			r.copy_from_spectrum(dr = spectrum_dynamic((float*)ra, (float*)(ra+9)));
			g.copy_from_spectrum(dg = spectrum_dynamic((float*)ga, (float*)(ga+9)));
			b.copy_from_spectrum(db = spectrum_dynamic((float*)ba, (float*)(ba+9)));
		}
		col3f wavelength_color(float wavelength) const
		{
			return col3f(r[wavelength], g[wavelength], b[wavelength]);
		}
		col3f spectrum_to_col3(const color_s& col) const
		{
			return embree::Col3f( (col*r).integral(), (col*g).integral(), (col*b).integral());
		}
		virtual void announce_properties(const std::string& prefix, property_announcer announcer)
		{
			announcer((prefix+".r").c_str(), ANNOUNCED_STRING, val_to_str(dr).c_str());
			announcer((prefix+".g").c_str(), ANNOUNCED_STRING, val_to_str(dg).c_str());
			announcer((prefix+".b").c_str(), ANNOUNCED_STRING, val_to_str(db).c_str());
		}
	protected:
		virtual err_t set_my_string(std::string& name, const std::string& value)
		{
			if(name == "r")
				r.copy_from_spectrum(dr = spectrum_dynamic(value, 0, 1));
			else if(name == "g")
				g.copy_from_spectrum(dg = spectrum_dynamic(value, 0, 1));
			else if(name == "b")
				b.copy_from_spectrum(db = spectrum_dynamic(value, 0, 1));
			else return ERR_BAD_PROP;
			return ERR_OK;
		}
		color_s r, g, b;
		spectrum_dynamic dr, dg, db; //for display only
	};

	
}
std::ostream& operator << (std::ostream& o, const gemren::spectrum& s);
std::ostream& operator << (std::ostream& o, const gemren::spectrum_dynamic& s);

#endif